package starfield.ui;

import starfield.mod.Mod;
import starfield.modpack.web.SyncingException;
import starfield.modpack.WebModpackDialog;
import starfield.modpack.ModpackDialog;
import starfield.modpack.Modpack;
import starfield.modpack.web.WebModpack;
import starfield.util.JFileSaver;
import java.awt.Desktop;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import javax.swing.ImageIcon;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.Document;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import starfield.Application;
import starfield.ParsingException;
import starfield.ValidationException;

public class MainFrame extends javax.swing.JFrame {

    private MainFrame() {
        initComponents();
		prepareDocuments();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        modpackContextMenu = new javax.swing.JPopupMenu();
        viewModpackInformationContextMenuItem = new javax.swing.JMenuItem();
        editModpackContextMenuItem = new javax.swing.JMenuItem();
        deleteModpackContextMenuItem = new javax.swing.JMenuItem();
        modpackContextMenuSeparator1 = new javax.swing.JPopupMenu.Separator();
        exportModpackContextMenuItem = new javax.swing.JMenuItem();
        hostModpackContextMenuItem = new javax.swing.JMenuItem();
        modpackContextMenuSeparator2 = new javax.swing.JPopupMenu.Separator();
        syncModpackContextMenuItem = new javax.swing.JMenuItem();
        cacheModpackContextMenuItem = new javax.swing.JMenuItem();
        modContextMenu = new javax.swing.JPopupMenu();
        viewModInformationContextMenuItem = new javax.swing.JMenuItem();
        deleteModContextMenuItem = new javax.swing.JMenuItem();
        moveUpModContextMenuItem = new javax.swing.JMenuItem();
        moveDownModContextMenuItem = new javax.swing.JMenuItem();
        addModpackContextMenu = new javax.swing.JPopupMenu();
        createNewModpackContextMenuItem = new javax.swing.JMenuItem();
        importNewModpackContextMenuItem = new javax.swing.JMenuItem();
        syncNewModpackContextMenuItem = new javax.swing.JMenuItem();
        modpacksPresentationLabel = new javax.swing.JLabel();
        modpacksToolBar = new javax.swing.JToolBar();
        addModpackSplitButton = new org.gpl.JSplitButton.JSplitButton();
        editModpackButton = new javax.swing.JButton();
        deleteModpackButton = new javax.swing.JButton();
        modpacksToolBarSeparator = new javax.swing.JToolBar.Separator();
        exportModpackButton = new javax.swing.JButton();
        hostModpackButton = new javax.swing.JButton();
        syncModpackButton = new javax.swing.JButton();
        cacheModpackButton = new javax.swing.JButton();
        modpackListPane = new javax.swing.JScrollPane();
        modpackList = new javax.swing.JTable() {
            public Class getColumnClass(int column)
            {
                Object value = getValueAt(0, column);

                if (value != null) {
                    return value.getClass();
                } else {
                    return String.class;
                }
            }
        };
        step1Panel = new javax.swing.JPanel();
        step1Label = new javax.swing.JLabel();
        moreInfoLabel = new javax.swing.JLabel();
        step2Panel = new javax.swing.JPanel();
        step2Label = new javax.swing.JLabel();
        compileButton = new javax.swing.JButton();
        step3Panel = new javax.swing.JPanel();
        step3Label = new javax.swing.JLabel();
        playButton = new javax.swing.JButton();
        tabbedPane = new javax.swing.JTabbedPane();
        modListPane = new javax.swing.JScrollPane();
        modList = new javax.swing.JTable();
        modpackInformationScrollPane = new javax.swing.JScrollPane();
        modpackInformationPane = new javax.swing.JEditorPane();
        modInformationScrollPane = new javax.swing.JScrollPane();
        modInformationPane = new javax.swing.JEditorPane();
        modsToolBar = new javax.swing.JToolBar();
        addModButton = new javax.swing.JButton();
        deleteModButton = new javax.swing.JButton();
        moveUpModButton = new javax.swing.JButton();
        moveDownModButton = new javax.swing.JButton();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        preferencesMenuItem = new javax.swing.JMenuItem();
        reloadMenuItem = new javax.swing.JMenuItem();
        exitMenuItem = new javax.swing.JMenuItem();
        modsMenu = new javax.swing.JMenu();
        addModMenuItem = new javax.swing.JMenuItem();
        deleteModMenuItem = new javax.swing.JMenuItem();
        moveUpModMenuItem = new javax.swing.JMenuItem();
        moveDownModMenuItem = new javax.swing.JMenuItem();
        modpacksMenu = new javax.swing.JMenu();
        addModpackMenu = new javax.swing.JMenu();
        createNewModpackMenuItem = new javax.swing.JMenuItem();
        importNewModpackMenuItem = new javax.swing.JMenuItem();
        syncNewModpackMenuItem = new javax.swing.JMenuItem();
        editModpackMenuItem = new javax.swing.JMenuItem();
        deleteModpackMenuItem = new javax.swing.JMenuItem();
        modpacksMenuSeparator1 = new javax.swing.JPopupMenu.Separator();
        exportModpackMenuItem = new javax.swing.JMenuItem();
        hostModpackMenuItem = new javax.swing.JMenuItem();
        modpacksMenuSeparator2 = new javax.swing.JPopupMenu.Separator();
        syncModpackMenuItem = new javax.swing.JMenuItem();
        cacheModpackMenuItem = new javax.swing.JMenuItem();

        viewModpackInformationContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/information.png"))); // NOI18N
        viewModpackInformationContextMenuItem.setText("View information");
        viewModpackInformationContextMenuItem.setEnabled(false);
        viewModpackInformationContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                viewModpackInformationContextMenuItemActionPerformed(evt);
            }
        });
        modpackContextMenu.add(viewModpackInformationContextMenuItem);

        editModpackContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_wrench.png"))); // NOI18N
        editModpackContextMenuItem.setText("Edit");
        editModpackContextMenuItem.setEnabled(false);
        editModpackContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editModpackContextMenuItemActionPerformed(evt);
            }
        });
        modpackContextMenu.add(editModpackContextMenuItem);

        deleteModpackContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_delete.png"))); // NOI18N
        deleteModpackContextMenuItem.setEnabled(false);
        deleteModpackContextMenuItem.setLabel("Delete");
        deleteModpackContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteModpackContextMenuItemActionPerformed(evt);
            }
        });
        modpackContextMenu.add(deleteModpackContextMenuItem);
        modpackContextMenu.add(modpackContextMenuSeparator1);

        exportModpackContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_go.png"))); // NOI18N
        exportModpackContextMenuItem.setText("Export");
        exportModpackContextMenuItem.setEnabled(false);
        exportModpackContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exportModpackContextMenuItemActionPerformed(evt);
            }
        });
        modpackContextMenu.add(exportModpackContextMenuItem);

        hostModpackContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_cloud.png"))); // NOI18N
        hostModpackContextMenuItem.setEnabled(false);
        hostModpackContextMenuItem.setLabel("Host");
        hostModpackContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                hostModpackContextMenuItemActionPerformed(evt);
            }
        });
        modpackContextMenu.add(hostModpackContextMenuItem);
        modpackContextMenu.add(modpackContextMenuSeparator2);

        syncModpackContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_link.png"))); // NOI18N
        syncModpackContextMenuItem.setEnabled(false);
        syncModpackContextMenuItem.setLabel("Sync");
        syncModpackContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                syncModpackContextMenuItemActionPerformed(evt);
            }
        });
        modpackContextMenu.add(syncModpackContextMenuItem);

        cacheModpackContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_save.png"))); // NOI18N
        cacheModpackContextMenuItem.setText("Cache");
        cacheModpackContextMenuItem.setEnabled(false);
        cacheModpackContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cacheModpackContextMenuItemActionPerformed(evt);
            }
        });
        modpackContextMenu.add(cacheModpackContextMenuItem);

        viewModInformationContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/information.png"))); // NOI18N
        viewModInformationContextMenuItem.setText("View information");
        viewModInformationContextMenuItem.setEnabled(false);
        viewModInformationContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                viewModInformationContextMenuItemActionPerformed(evt);
            }
        });
        modContextMenu.add(viewModInformationContextMenuItem);

        deleteModContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/plugin_delete.png"))); // NOI18N
        deleteModContextMenuItem.setEnabled(false);
        deleteModContextMenuItem.setLabel("Delete");
        deleteModContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteModContextMenuItemActionPerformed(evt);
            }
        });
        modContextMenu.add(deleteModContextMenuItem);

        moveUpModContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/arrow_up.png"))); // NOI18N
        moveUpModContextMenuItem.setText("Move up");
        moveUpModContextMenuItem.setEnabled(false);
        moveUpModContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                moveUpModContextMenuItemActionPerformed(evt);
            }
        });
        modContextMenu.add(moveUpModContextMenuItem);

        moveDownModContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/arrow_down.png"))); // NOI18N
        moveDownModContextMenuItem.setText("Move down");
        moveDownModContextMenuItem.setEnabled(false);
        moveDownModContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                moveDownModContextMenuItemActionPerformed(evt);
            }
        });
        modContextMenu.add(moveDownModContextMenuItem);

        createNewModpackContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_add.png"))); // NOI18N
        createNewModpackContextMenuItem.setText("Create new modpack...");
        createNewModpackContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                createNewModpackContextMenuItemActionPerformed(evt);
            }
        });
        addModpackContextMenu.add(createNewModpackContextMenuItem);

        importNewModpackContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package.png"))); // NOI18N
        importNewModpackContextMenuItem.setText("Import from file...");
        importNewModpackContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                importNewModpackContextMenuItemActionPerformed(evt);
            }
        });
        addModpackContextMenu.add(importNewModpackContextMenuItem);

        syncNewModpackContextMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_link.png"))); // NOI18N
        syncNewModpackContextMenuItem.setText("Sync from web directory...");
        syncNewModpackContextMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                syncNewModpackContextMenuItemActionPerformed(evt);
            }
        });
        addModpackContextMenu.add(syncNewModpackContextMenuItem);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Starfield");
        setLocationByPlatform(true);
        setMinimumSize(new java.awt.Dimension(900, 600));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowOpened(java.awt.event.WindowEvent evt) {
                formWindowOpened(evt);
            }
        });

        modpacksPresentationLabel.setText("Available modpacks:");

        modpacksToolBar.setFloatable(false);
        modpacksToolBar.setRollover(true);
        modpacksToolBar.setFocusable(false);

        addModpackSplitButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_add.png"))); // NOI18N
        addModpackSplitButton.setAlwaysDropDown(true);
        addModpackSplitButton.setFocusable(false);
        addModpackSplitButton.setLabel("Add");
        addModpackSplitButton.setMargin(new java.awt.Insets(0, 2, 0, 20));
        addModpackSplitButton.setPopupMenu(addModpackContextMenu);
        addModpackSplitButton.setVerticalTextPosition(3);
        modpacksToolBar.add(addModpackSplitButton);

        editModpackButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_wrench.png"))); // NOI18N
        editModpackButton.setText("Edit");
        editModpackButton.setEnabled(false);
        editModpackButton.setFocusable(false);
        editModpackButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        editModpackButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                editModpackButtonActionPerformed(evt);
            }
        });
        modpacksToolBar.add(editModpackButton);

        deleteModpackButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_delete.png"))); // NOI18N
        deleteModpackButton.setText("Delete");
        deleteModpackButton.setEnabled(false);
        deleteModpackButton.setFocusable(false);
        deleteModpackButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        deleteModpackButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteModpackButtonActionPerformed(evt);
            }
        });
        modpacksToolBar.add(deleteModpackButton);

        modpacksToolBarSeparator.setVisible(false);
        modpacksToolBar.add(modpacksToolBarSeparator);

        exportModpackButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_go.png"))); // NOI18N
        exportModpackButton.setText("Export");
        exportModpackButton.setFocusable(false);
        exportModpackButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        exportModpackButton.setVisible(false);
        exportModpackButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exportModpackButtonActionPerformed(evt);
            }
        });
        modpacksToolBar.add(exportModpackButton);

        hostModpackButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_cloud.png"))); // NOI18N
        hostModpackButton.setText("Host");
        hostModpackButton.setFocusable(false);
        hostModpackButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        hostModpackButton.setVisible(false);
        hostModpackButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                hostModpackButtonActionPerformed(evt);
            }
        });
        modpacksToolBar.add(hostModpackButton);

        syncModpackButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_link.png"))); // NOI18N
        syncModpackButton.setText("Sync");
        syncModpackButton.setFocusable(false);
        syncModpackButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        syncModpackButton.setVisible(false);
        syncModpackButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                syncModpackButtonActionPerformed(evt);
            }
        });
        modpacksToolBar.add(syncModpackButton);

        cacheModpackButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_save.png"))); // NOI18N
        cacheModpackButton.setText("Cache");
        cacheModpackButton.setFocusable(false);
        cacheModpackButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        cacheModpackButton.setVisible(false);
        cacheModpackButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cacheModpackButtonActionPerformed(evt);
            }
        });
        modpacksToolBar.add(cacheModpackButton);

        modpackList.setAutoCreateRowSorter(true);
        modpackList.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Object", "Type", "Modpack", "Author(s)", "Version"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, false, false, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        modpackList.setComponentPopupMenu(modpackContextMenu);
        modpackList.setRowHeight(20);
        modpackList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        modpackList.getSelectionModel().addListSelectionListener(
            new javax.swing.event.ListSelectionListener() {
                @Override
                public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                    modpackListSelectionChanged(evt);
                }
            }
        );

        modpackList.addMouseListener(new MouseAdapter()
            {
                @Override
                public void mousePressed(MouseEvent e)
                {
                    if (SwingUtilities.isRightMouseButton(e))
                    {
                        Point p = e.getPoint();
                        int rowNumber = modpackList.rowAtPoint(p);
                        ListSelectionModel model = modpackList.getSelectionModel();
                        model.setSelectionInterval(rowNumber, rowNumber);
                    }
                }
            });
            modpackListPane.setViewportView(modpackList);
            if (modpackList.getColumnModel().getColumnCount() > 0) {
                modpackList.getColumnModel().getColumn(0).setMinWidth(0);
                modpackList.getColumnModel().getColumn(0).setPreferredWidth(0);
                modpackList.getColumnModel().getColumn(0).setMaxWidth(0);
                modpackList.getColumnModel().getColumn(1).setResizable(false);
                modpackList.getColumnModel().getColumn(1).setPreferredWidth(16);
            }

            step1Panel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

            step1Label.setText("<html><strong>Step 1:</strong> Choose your modpack and mods above.</html>");

            moreInfoLabel.setText("<html>For more information about mods, modpacks and where to get them, visit <a href=\"http://code.google.com/\">the project page at Google Code</a>.</html>");

            javax.swing.GroupLayout step1PanelLayout = new javax.swing.GroupLayout(step1Panel);
            step1Panel.setLayout(step1PanelLayout);
            step1PanelLayout.setHorizontalGroup(
                step1PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(step1PanelLayout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(step1PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                        .addComponent(step1Label, javax.swing.GroupLayout.DEFAULT_SIZE, 241, Short.MAX_VALUE)
                        .addComponent(moreInfoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
                    .addContainerGap())
            );
            step1PanelLayout.setVerticalGroup(
                step1PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(step1PanelLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(step1Label, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(moreInfoLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 58, Short.MAX_VALUE)
                    .addContainerGap())
            );

            step2Panel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

            step2Label.setText("<html><strong>Step 2:</strong> Copy selected modpack to the game folder.</html>");

            compileButton.setText("Copy");
            compileButton.setEnabled(false);
            compileButton.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    compileButtonActionPerformed(evt);
                }
            });

            javax.swing.GroupLayout step2PanelLayout = new javax.swing.GroupLayout(step2Panel);
            step2Panel.setLayout(step2PanelLayout);
            step2PanelLayout.setHorizontalGroup(
                step2PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(step2PanelLayout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(step2PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(step2PanelLayout.createSequentialGroup()
                            .addComponent(compileButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addContainerGap())
                        .addGroup(step2PanelLayout.createSequentialGroup()
                            .addComponent(step2Label, javax.swing.GroupLayout.DEFAULT_SIZE, 267, Short.MAX_VALUE)
                            .addGap(17, 17, 17))))
            );
            step2PanelLayout.setVerticalGroup(
                step2PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(step2PanelLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(step2Label, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                    .addComponent(compileButton, javax.swing.GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)
                    .addContainerGap())
            );

            step3Panel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

            step3Label.setText("<html><strong>Step 3:</strong> Launch Starbound and enjoy!</html>");

            playButton.setText("Play");
            playButton.setEnabled(false);
            playButton.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    playButtonActionPerformed(evt);
                }
            });

            javax.swing.GroupLayout step3PanelLayout = new javax.swing.GroupLayout(step3Panel);
            step3Panel.setLayout(step3PanelLayout);
            step3PanelLayout.setHorizontalGroup(
                step3PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(step3PanelLayout.createSequentialGroup()
                    .addContainerGap()
                    .addGroup(step3PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(step3PanelLayout.createSequentialGroup()
                            .addComponent(step3Label, javax.swing.GroupLayout.DEFAULT_SIZE, 266, Short.MAX_VALUE)
                            .addGap(17, 17, 17))
                        .addGroup(step3PanelLayout.createSequentialGroup()
                            .addComponent(playButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addContainerGap())))
            );
            step3PanelLayout.setVerticalGroup(
                step3PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(step3PanelLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(step3Label, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGap(11, 11, 11)
                    .addComponent(playButton, javax.swing.GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)
                    .addContainerGap())
            );

            modList.setAutoCreateRowSorter(true);
            modList.setModel(new javax.swing.table.DefaultTableModel(
                new Object [][] {

                },
                new String [] {
                    "Object", "Mod", "Author(s)", "Version"
                }
            ) {
                boolean[] canEdit = new boolean [] {
                    false, false, false, false
                };

                public boolean isCellEditable(int rowIndex, int columnIndex) {
                    return canEdit [columnIndex];
                }
            });
            modList.setComponentPopupMenu(modContextMenu);
            modList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
            modList.getSelectionModel().addListSelectionListener(
                new javax.swing.event.ListSelectionListener() {
                    @Override
                    public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                        modListSelectionChanged(evt);
                    }
                }
            );

            modList.addMouseListener(new MouseAdapter()
                {
                    @Override
                    public void mousePressed(MouseEvent e)
                    {
                        if (SwingUtilities.isRightMouseButton(e))
                        {
                            Point p = e.getPoint();
                            int rowNumber = modList.rowAtPoint(p);
                            ListSelectionModel model = modList.getSelectionModel();
                            model.setSelectionInterval(rowNumber, rowNumber);
                        }
                    }
                });
                modListPane.setViewportView(modList);
                if (modList.getColumnModel().getColumnCount() > 0) {
                    modList.getColumnModel().getColumn(0).setMinWidth(0);
                    modList.getColumnModel().getColumn(0).setPreferredWidth(0);
                    modList.getColumnModel().getColumn(0).setMaxWidth(0);
                }

                tabbedPane.addTab("Mods in modpack", modListPane);

                modpackInformationPane.setEditable(false);
                modpackInformationPane.setContentType("text/html"); // NOI18N
                modpackInformationPane.addHyperlinkListener(new HyperlinkListener() {
                    @Override
                    public void hyperlinkUpdate(HyperlinkEvent e) {
                        if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
                            if(Desktop.isDesktopSupported()) {
                                try {
                                    Desktop.getDesktop().browse(e.getURL().toURI());
                                } catch (URISyntaxException | IOException ex) {

                                }
                            }
                        }
                    }
                });
                modpackInformationScrollPane.setViewportView(modpackInformationPane);

                tabbedPane.addTab("Modpack information", modpackInformationScrollPane);

                modInformationPane.setEditable(false);
                modInformationPane.setContentType("text/html"); // NOI18N
                modInformationPane.addHyperlinkListener(new HyperlinkListener() {
                    @Override
                    public void hyperlinkUpdate(HyperlinkEvent e) {
                        if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
                            if(Desktop.isDesktopSupported()) {
                                try {
                                    Desktop.getDesktop().browse(e.getURL().toURI());
                                } catch (URISyntaxException | IOException ex) {

                                }
                            }
                        }
                    }
                });
                modInformationScrollPane.setViewportView(modInformationPane);

                tabbedPane.addTab("Mod information", modInformationScrollPane);

                modsToolBar.setFloatable(false);
                modsToolBar.setRollover(true);
                modsToolBar.setFocusable(false);

                addModButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/plugin_add.png"))); // NOI18N
                addModButton.setText("Add");
                addModButton.setEnabled(false);
                addModButton.setFocusable(false);
                addModButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
                addModButton.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        addModButtonActionPerformed(evt);
                    }
                });
                modsToolBar.add(addModButton);

                deleteModButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/plugin_delete.png"))); // NOI18N
                deleteModButton.setText("Delete");
                deleteModButton.setEnabled(false);
                deleteModButton.setFocusable(false);
                deleteModButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
                deleteModButton.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        deleteModButtonActionPerformed(evt);
                    }
                });
                modsToolBar.add(deleteModButton);

                moveUpModButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/arrow_up.png"))); // NOI18N
                moveUpModButton.setText("Move up");
                moveUpModButton.setEnabled(false);
                moveUpModButton.setFocusable(false);
                moveUpModButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
                modsToolBar.add(moveUpModButton);

                moveDownModButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/arrow_down.png"))); // NOI18N
                moveDownModButton.setText("Move down");
                moveDownModButton.setEnabled(false);
                moveDownModButton.setFocusable(false);
                moveDownModButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
                modsToolBar.add(moveDownModButton);

                fileMenu.setText("File");

                preferencesMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/wrench.png"))); // NOI18N
                preferencesMenuItem.setText("Preferences...");
                preferencesMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        preferencesMenuItemActionPerformed(evt);
                    }
                });
                fileMenu.add(preferencesMenuItem);

                reloadMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/arrow_refresh.png"))); // NOI18N
                reloadMenuItem.setText("Reload mods and modpacks");
                reloadMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        reloadMenuItemActionPerformed(evt);
                    }
                });
                fileMenu.add(reloadMenuItem);

                exitMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/door_out.png"))); // NOI18N
                exitMenuItem.setText("Exit");
                exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        exitMenuItemActionPerformed(evt);
                    }
                });
                fileMenu.add(exitMenuItem);

                menuBar.add(fileMenu);

                modsMenu.setText("Mods");

                addModMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/plugin_add.png"))); // NOI18N
                addModMenuItem.setText("Add...");
                addModMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        addModMenuItemActionPerformed(evt);
                    }
                });
                modsMenu.add(addModMenuItem);

                deleteModMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/plugin_delete.png"))); // NOI18N
                deleteModMenuItem.setText("Delete");
                deleteModMenuItem.setEnabled(false);
                deleteModMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        deleteModMenuItemActionPerformed(evt);
                    }
                });
                modsMenu.add(deleteModMenuItem);

                moveUpModMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/arrow_up.png"))); // NOI18N
                moveUpModMenuItem.setText("Move up");
                moveUpModMenuItem.setEnabled(false);
                modsMenu.add(moveUpModMenuItem);

                moveDownModMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/arrow_down.png"))); // NOI18N
                moveDownModMenuItem.setText("Move down");
                moveDownModMenuItem.setEnabled(false);
                modsMenu.add(moveDownModMenuItem);

                menuBar.add(modsMenu);

                modpacksMenu.setText("Modpacks");

                addModpackMenu.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_add.png"))); // NOI18N
                addModpackMenu.setText("Add");

                createNewModpackMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_add.png"))); // NOI18N
                createNewModpackMenuItem.setText("Create new modpack...");
                createNewModpackMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        createNewModpackMenuItemActionPerformed(evt);
                    }
                });
                addModpackMenu.add(createNewModpackMenuItem);

                importNewModpackMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package.png"))); // NOI18N
                importNewModpackMenuItem.setText("Import from file...");
                importNewModpackMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        importNewModpackMenuItemActionPerformed(evt);
                    }
                });
                addModpackMenu.add(importNewModpackMenuItem);

                syncNewModpackMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_link.png"))); // NOI18N
                syncNewModpackMenuItem.setText("Sync from web directory...");
                syncNewModpackMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        syncNewModpackMenuItemActionPerformed(evt);
                    }
                });
                addModpackMenu.add(syncNewModpackMenuItem);

                modpacksMenu.add(addModpackMenu);

                editModpackMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_wrench.png"))); // NOI18N
                editModpackMenuItem.setText("Edit");
                editModpackMenuItem.setEnabled(false);
                editModpackMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        editModpackMenuItemActionPerformed(evt);
                    }
                });
                modpacksMenu.add(editModpackMenuItem);

                deleteModpackMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_delete.png"))); // NOI18N
                deleteModpackMenuItem.setText("Delete");
                deleteModpackMenuItem.setEnabled(false);
                deleteModpackMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        deleteModpackMenuItemActionPerformed(evt);
                    }
                });
                modpacksMenu.add(deleteModpackMenuItem);
                modpacksMenu.add(modpacksMenuSeparator1);

                exportModpackMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_go.png"))); // NOI18N
                exportModpackMenuItem.setText("Export");
                exportModpackMenuItem.setEnabled(false);
                exportModpackMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        exportModpackMenuItemActionPerformed(evt);
                    }
                });
                modpacksMenu.add(exportModpackMenuItem);

                hostModpackMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_cloud.png"))); // NOI18N
                hostModpackMenuItem.setText("Host");
                hostModpackMenuItem.setEnabled(false);
                hostModpackMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        hostModpackMenuItemActionPerformed(evt);
                    }
                });
                modpacksMenu.add(hostModpackMenuItem);
                modpacksMenu.add(modpacksMenuSeparator2);

                syncModpackMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_link.png"))); // NOI18N
                syncModpackMenuItem.setText("Sync");
                syncModpackMenuItem.setEnabled(false);
                syncModpackMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        syncModpackMenuItemActionPerformed(evt);
                    }
                });
                modpacksMenu.add(syncModpackMenuItem);

                cacheModpackMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/starfield/icons/package_save.png"))); // NOI18N
                cacheModpackMenuItem.setText("Cache");
                cacheModpackMenuItem.setEnabled(false);
                cacheModpackMenuItem.addActionListener(new java.awt.event.ActionListener() {
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        cacheModpackMenuItemActionPerformed(evt);
                    }
                });
                modpacksMenu.add(cacheModpackMenuItem);

                menuBar.add(modpacksMenu);

                setJMenuBar(menuBar);

                javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
                getContentPane().setLayout(layout);
                layout.setHorizontalGroup(
                    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(modpacksToolBar, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 431, Short.MAX_VALUE)
                                    .addComponent(modpackListPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                                    .addComponent(modpacksPresentationLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 443, Short.MAX_VALUE)
                                    .addComponent(modsToolBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(step1Panel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(step2Panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(step3Panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                        .addContainerGap())
                );
                layout.setVerticalGroup(
                    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(6, 6, 6)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(modpacksPresentationLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(modpackListPane, javax.swing.GroupLayout.DEFAULT_SIZE, 346, Short.MAX_VALUE))
                            .addComponent(tabbedPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(modpacksToolBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(modsToolBar, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(step2Panel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(step3Panel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(step1Panel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addContainerGap())
                );

                pack();
                setLocationRelativeTo(null);
            }// </editor-fold>//GEN-END:initComponents
		
	private void updateModpackList() {
		DefaultTableModel model = (DefaultTableModel)modpackList.getModel();
		
		int rows = model.getRowCount(); 
		
		for(int i = rows - 1; i >=0; i--)
		{
			model.removeRow(i); 
		}
		
		for (Modpack modpack : Application.getModpacks()) {
			boolean isWeb = modpack instanceof WebModpack;
			boolean isInvalid = isWeb && ((WebModpack)modpack).isInvalid();
			
			String iconString = isWeb ? (isInvalid ? "link_error.png" : "link.png") : "drive.png";
			
			ImageIcon icon = new ImageIcon(getClass().getResource("/starfield/icons/" + iconString));
			
			Object[] row;
			
			if (isInvalid) {
				row = new Object[] {
					modpack,
					icon,
					modpack.getName(),
					null,
					null
				};
			} else {
				row = new Object[] {
					modpack,
					icon,
					modpack.getMetadata().getTitle(),
					modpack.getMetadata().getAuthorsString(),
					modpack.getMetadata().getVersion().toString()
				};
			}
			
			model.addRow(row);
		}
	}
	
	private void updateModList() {
		DefaultTableModel model = (DefaultTableModel)modList.getModel();
		
		int rows = model.getRowCount(); 
		
		for(int i = rows - 1; i >=0; i--)
		{
			model.removeRow(i); 
		}
		
		Modpack selectedModpack = getSelectedModpack();
		
		if (selectedModpack != null) {
			for (Mod mod : selectedModpack.getMods()) {
				Object[] row = new Object[] {
					mod,
					mod.getMetadata().getTitle(),
					mod.getMetadata().getAuthorsString(),
					mod.getMetadata().getVersion().toString()
				};

				model.addRow(row);
			}
		}
	}
	
	private Modpack getSelectedModpack() {
		if (modpackList.getSelectedRowCount() == 1) {
			return (Modpack)modpackList.getModel().getValueAt(modpackList.convertRowIndexToModel(modpackList.getSelectedRow()), 0);
		} else {
			return null;
		}
	}
	
	private Mod getSelectedMod() {
		if (getSelectedModpack() != null && modList.getSelectedRowCount() == 1) {
			return (Mod)modList.getModel().getValueAt(modList.convertRowIndexToModel(modList.getSelectedRow()), 0);
		} else {
			return null;
		}
	}
	
	private void selectModpack(Modpack modpack) {
		modpackList.clearSelection();
		
		for (int i = 0; i < modpackList.getModel().getRowCount(); i++) {
			int vi = modpackList.convertRowIndexToView(i);
			
			if (modpack == modpackList.getModel().getValueAt(i, 0)) {
				modpackList.setRowSelectionInterval(vi, vi);
				break;
			}
		}
	}
	
	private void selectMod(Mod mod) {
		modList.clearSelection();
		
		for (int i = 0; i < modList.getModel().getRowCount(); i++) {
			int vi = modList.convertRowIndexToView(i);
			
			if (mod == modList.getModel().getValueAt(i, 0)) {
				modList.setRowSelectionInterval(vi, vi);
				break;
			}
		}
	}
	
	private static Document createStyledDocument(JEditorPane editorPane) {
		HTMLEditorKit kit = (HTMLEditorKit)editorPane.getEditorKit();
		StyleSheet styleSheet = kit.getStyleSheet();
		styleSheet.addRule("body { font-family: sans-serif; margin: 0 10px; }");
		styleSheet.addRule("h1, h2, h3, h4, h5 { margin: 0px; margin-top: 10px; }");
		styleSheet.addRule("p { margin: 5px 0px; }");
		styleSheet.addRule("blockquote { border-style: solid; border-color: #5599FF; background: #cceeff; margin-left: 10px; padding: 0 10px; font-style: italic; }");
		styleSheet.addRule("pre { border-style: solid; border-color: gray; background: #efefef; margin-left: 10px; padding: 10px; }");
		return kit.createDefaultDocument();
	}
	
	private void prepareDocuments() {
		Document modpackDoc = createStyledDocument(modpackInformationPane);
		Document modDoc = createStyledDocument(modInformationPane);
		modpackInformationPane.setDocument(modpackDoc);
		modInformationPane.setDocument(modDoc);
	}
	
	private void updateModpackInformation() {
		Modpack selectedModpack = getSelectedModpack();
		
		String html = "<html><body>";
		html += selectedModpack == null ? "" : selectedModpack.toHtmlString();
		html += "</html></body>";
		
		modpackInformationPane.setText(html);
		modpackInformationPane.setCaretPosition(0);
	}
	
	private void updateModInformation() {
		Mod selectedMod = getSelectedMod();
		
		String html = "<html><body>";
		html += selectedMod == null ? "" : selectedMod.toHtmlString();
		html += "</html></body>";
		
		modInformationPane.setText(html);
		modInformationPane.setCaretPosition(0);
	}
	
	private void createNewLocalModpack() {
		ModpackDialog modpackDialog = ModpackDialog.show(this, true);

		if (modpackDialog.hasAnswered()) {
			try {
				Modpack newModpack = Modpack.create(modpackDialog);
				updateModpackList();
				selectModpack(newModpack);
			} catch (IOException | ValidationException ex) {
				JOptionPane.showMessageDialog(
					this, 
					"Could not create modpack: " + 
					System.lineSeparator() + System.lineSeparator() + 
					ex.getMessage(), 
					"New modpack", 
					JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	private void addMod() {
		Modpack selectedModpack = getSelectedModpack();
		
		if (selectedModpack != null) {
			JFileChooser fileChooser = new JFileChooser();
			FileNameExtensionFilter filter = new FileNameExtensionFilter("Starfield Mod files (*." + Mod.EXTENSION + ")", Mod.EXTENSION);
			fileChooser.setFileFilter(filter);
			fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

			if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
				try {
					File addModFile = fileChooser.getSelectedFile();
					File newModFile = new File(selectedModpack.getDirectoryPath() + File.separator + addModFile.getName());

					if (newModFile.exists() && newModFile.isFile()) {
						if (JOptionPane.showConfirmDialog(
								this, 
								"The mod file '" + newModFile.getName() + "' already exists in this modpack. Overwrite it?",
								"Overwrite mod",
								JOptionPane.YES_NO_CANCEL_OPTION) == JOptionPane.YES_OPTION) {
							
							FileUtils.copyFile(addModFile, newModFile, true);
							
							Mod oldMod = selectedModpack.findMod(newModFile.getName());
							
							if (oldMod != null) {
								selectedModpack.getMods().remove(oldMod);
							}
							
							Mod newMod = Mod.load(selectedModpack, newModFile.getName());
							updateModList();
							selectMod(newMod);
						}
					} else {
						FileUtils.copyFile(addModFile, newModFile, true);
						
						Mod newMod = Mod.load(selectedModpack, newModFile.getName());
						updateModList();
						selectMod(newMod);
					}
				} catch (IOException | ParsingException ex) {
					JOptionPane.showMessageDialog(
						this, 
						"Could not add mod file: " + 
						System.lineSeparator() + System.lineSeparator() + 
						ex.getMessage(), 
						"Add mod", 
						JOptionPane.ERROR_MESSAGE);
				}
			}
		}
	}
	
	private void importNewModpack() {
		JFileChooser fileChooser = new JFileChooser();
		FileNameExtensionFilter filter = new FileNameExtensionFilter("Starfield modpack files (*." + Modpack.EXTENSION + ")", Modpack.EXTENSION);
		fileChooser.setFileFilter(filter);
		fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

		if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
			try {
				File addModpackFile = fileChooser.getSelectedFile();
				String newModpackDirectoryName = FilenameUtils.removeExtension(addModpackFile.getName());
				File newModpackDirectory = new File(Modpack.getModpacksDirectoryPath() + File.separator + newModpackDirectoryName);

				if (newModpackDirectory.exists() && newModpackDirectory.isDirectory()) {
					if (JOptionPane.showConfirmDialog(
							this, 
							"The modpack directory '" + newModpackDirectory.getName() + "' already exists. Overwrite it?",
							"Overwrite modpack",
							JOptionPane.YES_NO_CANCEL_OPTION) == JOptionPane.YES_OPTION) {
						    
						String source = "some/compressed/file.zip";
						String destination = "some/destination/folder";
						String password = "password";

						new ZipFile(addModpackFile).extractAll(newModpackDirectory.getAbsolutePath());

						Modpack oldModpack = Application.findModpack(newModpackDirectory.getName());

						if (oldModpack != null) {
							Application.getModpacks().remove(oldModpack);
						}
						
						Modpack newModpack = Modpack.load(newModpackDirectory.getName());
						updateModpackList();
						selectModpack(newModpack);
					}
				} else {
					new ZipFile(addModpackFile).extractAll(newModpackDirectory.getAbsolutePath());
					
					Modpack newModpack = Modpack.load(newModpackDirectory.getName());
					updateModpackList();
					selectModpack(newModpack);
				}

			} catch (IOException | ParsingException | ZipException ex) {
				JOptionPane.showMessageDialog(
					this, 
					"Could not import modpack file: " + 
					System.lineSeparator() + System.lineSeparator() + 
					ex.getMessage(), 
					"Import modpack", 
					JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	private void createNewWebModpack() {
		WebModpackDialog modpackDialog = WebModpackDialog.show(this, true);

		if (modpackDialog.hasAnswered()) {
			try {
				WebModpack newModpack = WebModpack.create(modpackDialog);
				updateModpackList();
				selectModpack(newModpack);
			} catch (IOException | ValidationException | SyncingException | ParsingException ex) {
				JOptionPane.showMessageDialog(
					this, 
					"Could not create web modpack: " + 
					System.lineSeparator() + System.lineSeparator() + 
					ex.getMessage(), 
					"New web modpack", 
					JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	private void editSelectedModpack() {
		Modpack selectedModpack = getSelectedModpack();
			
		if (selectedModpack != null) {
			if (selectedModpack instanceof WebModpack) {
				editSelectedWebModpack();
			} else {
				editSelectedLocalModpack();
			}
		}
	}
	
	private void editSelectedLocalModpack() {
		Modpack selectedModpack = getSelectedModpack();
			
		if (selectedModpack != null) {
			ModpackDialog modpackDialog = ModpackDialog.show(this, true, selectedModpack);
			
			if (modpackDialog.hasAnswered()) {
				try {
					modpackDialog.fillModpack(selectedModpack);
					selectedModpack.save();
				} catch (IOException | ValidationException ex) {
					JOptionPane.showMessageDialog(
						this, 
						"Could not save modpack configuration: " + 
						System.lineSeparator() + System.lineSeparator() + 
						ex.getMessage(), 
						"Edit modpack", 
						JOptionPane.ERROR_MESSAGE);
				}
				
				if (modpackDialog.hasDirectoryNameChanged()) {
					try {
						selectedModpack.renameDirectory(modpackDialog.getDirectoryName());
					} catch (IOException | ValidationException ex) {
						JOptionPane.showMessageDialog(
							this, 
							"Could not rename modpack directory: " + 
							System.lineSeparator() + System.lineSeparator() + 
							ex.getMessage(), 
							"Edit modpack", 
							JOptionPane.ERROR_MESSAGE);
					}
				}
				
				updateModpackList();
				selectModpack(selectedModpack);
			}
		}
	}
	
	private void editSelectedWebModpack() {
		WebModpack selectedModpack = (WebModpack)getSelectedModpack();
			
		if (selectedModpack != null) {
			WebModpackDialog modpackDialog = WebModpackDialog.show(this, true, selectedModpack);
			
			if (modpackDialog.hasAnswered()) {
				if (modpackDialog.hasDirectoryNameChanged()) {
					try {
						selectedModpack.renameDirectory(modpackDialog.getDirectoryName());
					} catch (IOException | ValidationException ex) {
						JOptionPane.showMessageDialog(
							this, 
							"Could not rename modpack directory: " + 
							System.lineSeparator() + System.lineSeparator() + 
							ex.getMessage(), 
							"Edit web modpack", 
							JOptionPane.ERROR_MESSAGE);
					}
				}
				
				try {
					modpackDialog.fillModpack(selectedModpack);
					Application.saveWebModpacksList();
				} catch (IOException | ValidationException ex) {
					JOptionPane.showMessageDialog(
						this, 
						"Could not save web modpack connection configuration: " + 
						System.lineSeparator() + System.lineSeparator() + 
						ex.getMessage(), 
						"Edit web modpack", 
						JOptionPane.ERROR_MESSAGE);
				}
				
				try {
					selectedModpack.sync(false);
				} catch (SyncingException ex) {
					JOptionPane.showMessageDialog(
						this, 
						"Could not sync web modpack: " + 
						System.lineSeparator() + System.lineSeparator() + 
						ex.getMessage(), 
						"Edit web modpack", 
						JOptionPane.ERROR_MESSAGE);
				}
				
				updateModpackList();
				selectModpack(selectedModpack);
			}
		}
	}
	
	private void deleteSelectedModpack() {
		Modpack selectedModpack = getSelectedModpack();
			
		if (selectedModpack != null) {
			if (JOptionPane.showConfirmDialog(
				this, 
				"Are you sure you want to delete the modpack '" + selectedModpack.getDisplayName() + "'?", 
				"Delete modpack", 
				JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {

				try {
					selectedModpack.delete();
					Application.getModpacks().remove(selectedModpack);
					updateModpackList();
				
					if (selectedModpack instanceof WebModpack) {
						Application.saveWebModpacksList();
					}
				} catch (IOException ex) {
					JOptionPane.showMessageDialog(
						this, 
						"Could not delete modpack: " + 
						System.lineSeparator() + System.lineSeparator() + 
						ex.getMessage(), 
						"Delete modpack", 
						JOptionPane.ERROR_MESSAGE);
				}
			}
		}
	}
	
	private void deleteSelectedMod() {
		Modpack selectedModpack = getSelectedModpack();
		Mod selectedMod = getSelectedMod();
			
		if (selectedMod != null) {

			if (JOptionPane.showConfirmDialog(
				this, 
				"Are you sure you want to delete the mod '" + selectedMod.getDisplayName()+ "'?", 
				"Delete mod", 
				JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {

				try {
					selectedMod.delete();
					selectedModpack.getMods().remove(selectedMod);
					updateModList();
				} catch (IOException ex) {
					JOptionPane.showMessageDialog(
						this, 
						"Could not delete mod: " + 
						System.lineSeparator() + System.lineSeparator() + 
						ex.getMessage(), 
						"Delete mod", 
						JOptionPane.ERROR_MESSAGE);
				}
			}
		}
	}
	
	private void exportSelectedModpack() {
		Modpack selectedModpack = getSelectedModpack();
		
		if (selectedModpack != null) {
			JFileSaver fileChooser = new JFileSaver();
			FileNameExtensionFilter filter = new FileNameExtensionFilter("Starfield Modpack files (*." + Modpack.EXTENSION + ")", Modpack.EXTENSION);
			fileChooser.setFileFilter(filter);
			fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
			fileChooser.setSelectedFile(new File(selectedModpack.getName() + "." + Modpack.EXTENSION));
			
			if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
				try {
					File exportedFile = fileChooser.getSelectedFile();
					selectedModpack.export(exportedFile.getAbsolutePath());
				} catch (IOException | ZipException ex) {
					JOptionPane.showMessageDialog(
						this, 
						"Could not export modpack file: " + 
						System.lineSeparator() + System.lineSeparator() + 
						ex.getMessage(), 
						"Export modpack", 
						JOptionPane.ERROR_MESSAGE);
				}
			}
		}
	}
	
	private void syncSelectedModpack() {
		Modpack selectedModpack = getSelectedModpack();
			
		if (selectedModpack != null && selectedModpack instanceof WebModpack) {
			WebModpack selectedWebModpack = (WebModpack)selectedModpack;
			
			try {
				selectedWebModpack.sync(false);
			} catch (SyncingException ex) {
				JOptionPane.showMessageDialog(
					this, 
					"Could not sync modpack: " + 
					System.lineSeparator() + System.lineSeparator() + 
					ex.getMessage(), 
					"Sync modpack", 
					JOptionPane.ERROR_MESSAGE);
			}

			updateModpackList();
			selectModpack(selectedModpack);
		}
	}
	
	private void cacheSelectedModpack() {
		
	}
	
	private void hostSelectedModpack() {
		
	}
	
	private void moveUpSelectedMod() {
		
	}
	
	private void moveDownSelectedMod() {
		
	}
	
	private void reloadModpacksAndMods() {
		JOptionPane.showMessageDialog(
			this, 
			"This functionality is used for debug purposes."
			+ System.lineSeparator() + System.lineSeparator() + 
			"Editing any Starfield file or folder while the application " + System.lineSeparator() + 
			"is running can cause instability and loss of data.", 
			"Reload mods and modpacks", 
			JOptionPane.WARNING_MESSAGE);
		
		try {
			Application.loadModpacks();
			updateModpackList();
			updateModList();
			
			JOptionPane.showMessageDialog(
				this, 
				"Successfully reloaded mods and modpacks.", 
				"Reload mods and modpacks", 
				JOptionPane.INFORMATION_MESSAGE);
		} catch (IOException | ParsingException ex) {
			JOptionPane.showMessageDialog(
				this, 
				"Failed to reload mods and modpacks: " + 
				System.lineSeparator() + System.lineSeparator() + 
				ex.getMessage(), 
				"Reload mods and modpacks", 
				JOptionPane.ERROR_MESSAGE);
			
			dispose();
		}
	} 
	
	private void compileSelectedModpack() {
		Modpack selectedModpack = getSelectedModpack();
			
		if (selectedModpack != null) {
			try {

			} catch (Exception ex) {
				ex.printStackTrace();
				
				JOptionPane.showMessageDialog(
					this, 
					"Compilation failed: " + 
					System.lineSeparator() + System.lineSeparator() + 
					ex.getMessage(), 
					"Compile modpack", 
					JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
    private void preferencesMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_preferencesMenuItemActionPerformed
		PreferencesFrame.launch(false);
    }//GEN-LAST:event_preferencesMenuItemActionPerformed

    private void createNewModpackMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createNewModpackMenuItemActionPerformed
        createNewLocalModpack();
    }//GEN-LAST:event_createNewModpackMenuItemActionPerformed

    private void deleteModpackButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteModpackButtonActionPerformed
		deleteSelectedModpack();
    }//GEN-LAST:event_deleteModpackButtonActionPerformed

    private void deleteModpackMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteModpackMenuItemActionPerformed
		deleteSelectedModpack();
    }//GEN-LAST:event_deleteModpackMenuItemActionPerformed

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
		dispose();
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void editModpackMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editModpackMenuItemActionPerformed
		editSelectedModpack();
    }//GEN-LAST:event_editModpackMenuItemActionPerformed

    private void editModpackButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editModpackButtonActionPerformed
		editSelectedModpack();
    }//GEN-LAST:event_editModpackButtonActionPerformed

    private void viewModpackInformationContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewModpackInformationContextMenuItemActionPerformed
		tabbedPane.setSelectedComponent(modpackInformationScrollPane);
    }//GEN-LAST:event_viewModpackInformationContextMenuItemActionPerformed

    private void viewModInformationContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_viewModInformationContextMenuItemActionPerformed
		tabbedPane.setSelectedComponent(modInformationScrollPane);
    }//GEN-LAST:event_viewModInformationContextMenuItemActionPerformed

    private void deleteModButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteModButtonActionPerformed
		deleteSelectedMod();
    }//GEN-LAST:event_deleteModButtonActionPerformed

    private void deleteModMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteModMenuItemActionPerformed
		deleteSelectedMod();
    }//GEN-LAST:event_deleteModMenuItemActionPerformed

    private void reloadMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_reloadMenuItemActionPerformed
		reloadModpacksAndMods();
    }//GEN-LAST:event_reloadMenuItemActionPerformed

    private void addModButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addModButtonActionPerformed
		addMod();
    }//GEN-LAST:event_addModButtonActionPerformed

    private void playButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_playButtonActionPerformed
		
    }//GEN-LAST:event_playButtonActionPerformed

    private void editModpackContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editModpackContextMenuItemActionPerformed
		editSelectedModpack();
    }//GEN-LAST:event_editModpackContextMenuItemActionPerformed

    private void deleteModpackContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteModpackContextMenuItemActionPerformed
		deleteSelectedModpack();
    }//GEN-LAST:event_deleteModpackContextMenuItemActionPerformed

    private void exportModpackContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportModpackContextMenuItemActionPerformed
		exportSelectedModpack();
    }//GEN-LAST:event_exportModpackContextMenuItemActionPerformed

    private void hostModpackContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hostModpackContextMenuItemActionPerformed
		hostSelectedModpack();
    }//GEN-LAST:event_hostModpackContextMenuItemActionPerformed

    private void cacheModpackContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cacheModpackContextMenuItemActionPerformed
		cacheSelectedModpack();
    }//GEN-LAST:event_cacheModpackContextMenuItemActionPerformed

    private void exportModpackButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportModpackButtonActionPerformed
		exportSelectedModpack();
    }//GEN-LAST:event_exportModpackButtonActionPerformed

    private void addModMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addModMenuItemActionPerformed
		addMod();
    }//GEN-LAST:event_addModMenuItemActionPerformed

    private void cacheModpackButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cacheModpackButtonActionPerformed
		cacheSelectedModpack();
    }//GEN-LAST:event_cacheModpackButtonActionPerformed

    private void hostModpackButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hostModpackButtonActionPerformed
		hostSelectedModpack();
    }//GEN-LAST:event_hostModpackButtonActionPerformed

    private void exportModpackMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportModpackMenuItemActionPerformed
		exportSelectedModpack();
    }//GEN-LAST:event_exportModpackMenuItemActionPerformed

    private void cacheModpackMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cacheModpackMenuItemActionPerformed
		cacheSelectedModpack();
    }//GEN-LAST:event_cacheModpackMenuItemActionPerformed

    private void hostModpackMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hostModpackMenuItemActionPerformed
		hostSelectedModpack();
    }//GEN-LAST:event_hostModpackMenuItemActionPerformed

    private void importNewModpackMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importNewModpackMenuItemActionPerformed
		importNewModpack();
    }//GEN-LAST:event_importNewModpackMenuItemActionPerformed

    private void syncNewModpackMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_syncNewModpackMenuItemActionPerformed
		createNewWebModpack();
    }//GEN-LAST:event_syncNewModpackMenuItemActionPerformed

    private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened
		try {
			Application.loadModpacks();
			updateModpackList();
		} catch (IOException | ParsingException ex) {
			JOptionPane.showMessageDialog(
				this, 
				"Failed to load mods and modpacks: " + 
				System.lineSeparator() + System.lineSeparator() + 
				ex.getMessage(), 
				"Starfield", 
				JOptionPane.ERROR_MESSAGE);
			
			dispose();
		}
    }//GEN-LAST:event_formWindowOpened

    private void syncModpackButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_syncModpackButtonActionPerformed
		syncSelectedModpack();
    }//GEN-LAST:event_syncModpackButtonActionPerformed

    private void syncModpackMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_syncModpackMenuItemActionPerformed
		syncSelectedModpack();
    }//GEN-LAST:event_syncModpackMenuItemActionPerformed

    private void syncModpackContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_syncModpackContextMenuItemActionPerformed
		syncSelectedModpack();
    }//GEN-LAST:event_syncModpackContextMenuItemActionPerformed

    private void createNewModpackContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createNewModpackContextMenuItemActionPerformed
		createNewLocalModpack();
    }//GEN-LAST:event_createNewModpackContextMenuItemActionPerformed

    private void importNewModpackContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importNewModpackContextMenuItemActionPerformed
		importNewModpack();
    }//GEN-LAST:event_importNewModpackContextMenuItemActionPerformed

    private void syncNewModpackContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_syncNewModpackContextMenuItemActionPerformed
		createNewWebModpack();
    }//GEN-LAST:event_syncNewModpackContextMenuItemActionPerformed

    private void deleteModContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteModContextMenuItemActionPerformed
		deleteSelectedMod();
    }//GEN-LAST:event_deleteModContextMenuItemActionPerformed

    private void moveUpModContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveUpModContextMenuItemActionPerformed
		moveUpSelectedMod();
    }//GEN-LAST:event_moveUpModContextMenuItemActionPerformed

    private void moveDownModContextMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveDownModContextMenuItemActionPerformed
		moveDownSelectedMod();
    }//GEN-LAST:event_moveDownModContextMenuItemActionPerformed

    private void compileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_compileButtonActionPerformed
		compileSelectedModpack();
    }//GEN-LAST:event_compileButtonActionPerformed

	private void modpackListSelectionChanged(javax.swing.event.ListSelectionEvent evt) {
		updateModpackInformation();
		updateModList();
		
		Modpack selectedModpack = getSelectedModpack();
		
		boolean enabled = selectedModpack != null;
		boolean webEnabled = enabled && selectedModpack instanceof WebModpack;
		boolean validWebEnabled = webEnabled && !((WebModpack)selectedModpack).isInvalid();
		boolean localEnabled = enabled && !webEnabled;
		
		editModpackButton.setEnabled(enabled);
		editModpackContextMenuItem.setEnabled(enabled);
		editModpackMenuItem.setEnabled(enabled);
		
		deleteModpackButton.setEnabled(enabled);
		deleteModpackContextMenuItem.setEnabled(enabled);
		deleteModpackMenuItem.setEnabled(enabled);
		
		exportModpackButton.setVisible(localEnabled);
		exportModpackContextMenuItem.setEnabled(localEnabled);
		exportModpackMenuItem.setEnabled(localEnabled);
		
		hostModpackButton.setVisible(localEnabled);
		hostModpackContextMenuItem.setEnabled(localEnabled);
		hostModpackMenuItem.setEnabled(localEnabled);
		
		syncModpackButton.setVisible(webEnabled);
		syncModpackContextMenuItem.setEnabled(webEnabled);
		syncModpackMenuItem.setEnabled(webEnabled);
		
		cacheModpackButton.setVisible(validWebEnabled);
		cacheModpackContextMenuItem.setEnabled(validWebEnabled);
		cacheModpackMenuItem.setEnabled(validWebEnabled);

		modpacksToolBarSeparator.setVisible(enabled);
		viewModpackInformationContextMenuItem.setEnabled(enabled);
		addModButton.setEnabled(localEnabled);
		requireCompile();
		compileButton.setEnabled(enabled);
	}
	
	private void modListSelectionChanged(javax.swing.event.ListSelectionEvent evt) {
		updateModInformation();
		
		Mod selectedMod = getSelectedMod();
		Modpack selectedModpack = getSelectedModpack();
		
		boolean enabled = selectedMod != null;
		boolean webEnabled = enabled && selectedModpack instanceof WebModpack;
		boolean localEnabled = enabled && !webEnabled;

		deleteModButton.setEnabled(localEnabled);
		deleteModMenuItem.setEnabled(localEnabled);
		deleteModContextMenuItem.setEnabled(localEnabled);
		
		moveUpModButton.setEnabled(localEnabled);
		moveUpModMenuItem.setEnabled(localEnabled);
		moveUpModContextMenuItem.setEnabled(localEnabled);
		
		moveDownModButton.setEnabled(localEnabled);
		moveDownModMenuItem.setEnabled(localEnabled);
		moveDownModContextMenuItem.setEnabled(localEnabled);
		
		viewModInformationContextMenuItem.setEnabled(enabled);
	}
	
	public void requireCompile() {
		compileButton.setEnabled(true);
		playButton.setEnabled(false);
	}
	
    public static void launch() {
        java.awt.EventQueue.invokeLater(new Runnable() {
			@Override
            public void run() {
				Application.setMainFrame(new MainFrame());
                Application.getMainFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addModButton;
    private javax.swing.JMenuItem addModMenuItem;
    private javax.swing.JPopupMenu addModpackContextMenu;
    private javax.swing.JMenu addModpackMenu;
    private org.gpl.JSplitButton.JSplitButton addModpackSplitButton;
    private javax.swing.JButton cacheModpackButton;
    private javax.swing.JMenuItem cacheModpackContextMenuItem;
    private javax.swing.JMenuItem cacheModpackMenuItem;
    private javax.swing.JButton compileButton;
    private javax.swing.JMenuItem createNewModpackContextMenuItem;
    private javax.swing.JMenuItem createNewModpackMenuItem;
    private javax.swing.JButton deleteModButton;
    private javax.swing.JMenuItem deleteModContextMenuItem;
    private javax.swing.JMenuItem deleteModMenuItem;
    private javax.swing.JButton deleteModpackButton;
    private javax.swing.JMenuItem deleteModpackContextMenuItem;
    private javax.swing.JMenuItem deleteModpackMenuItem;
    private javax.swing.JButton editModpackButton;
    private javax.swing.JMenuItem editModpackContextMenuItem;
    private javax.swing.JMenuItem editModpackMenuItem;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JButton exportModpackButton;
    private javax.swing.JMenuItem exportModpackContextMenuItem;
    private javax.swing.JMenuItem exportModpackMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JButton hostModpackButton;
    private javax.swing.JMenuItem hostModpackContextMenuItem;
    private javax.swing.JMenuItem hostModpackMenuItem;
    private javax.swing.JMenuItem importNewModpackContextMenuItem;
    private javax.swing.JMenuItem importNewModpackMenuItem;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JPopupMenu modContextMenu;
    private javax.swing.JEditorPane modInformationPane;
    private javax.swing.JScrollPane modInformationScrollPane;
    private javax.swing.JTable modList;
    private javax.swing.JScrollPane modListPane;
    private javax.swing.JPopupMenu modpackContextMenu;
    private javax.swing.JPopupMenu.Separator modpackContextMenuSeparator1;
    private javax.swing.JPopupMenu.Separator modpackContextMenuSeparator2;
    private javax.swing.JEditorPane modpackInformationPane;
    private javax.swing.JScrollPane modpackInformationScrollPane;
    private javax.swing.JTable modpackList;
    private javax.swing.JScrollPane modpackListPane;
    private javax.swing.JMenu modpacksMenu;
    private javax.swing.JPopupMenu.Separator modpacksMenuSeparator1;
    private javax.swing.JPopupMenu.Separator modpacksMenuSeparator2;
    private javax.swing.JLabel modpacksPresentationLabel;
    private javax.swing.JToolBar modpacksToolBar;
    private javax.swing.JToolBar.Separator modpacksToolBarSeparator;
    private javax.swing.JMenu modsMenu;
    private javax.swing.JToolBar modsToolBar;
    private javax.swing.JLabel moreInfoLabel;
    private javax.swing.JButton moveDownModButton;
    private javax.swing.JMenuItem moveDownModContextMenuItem;
    private javax.swing.JMenuItem moveDownModMenuItem;
    private javax.swing.JButton moveUpModButton;
    private javax.swing.JMenuItem moveUpModContextMenuItem;
    private javax.swing.JMenuItem moveUpModMenuItem;
    private javax.swing.JButton playButton;
    private javax.swing.JMenuItem preferencesMenuItem;
    private javax.swing.JMenuItem reloadMenuItem;
    private javax.swing.JLabel step1Label;
    private javax.swing.JPanel step1Panel;
    private javax.swing.JLabel step2Label;
    private javax.swing.JPanel step2Panel;
    private javax.swing.JLabel step3Label;
    private javax.swing.JPanel step3Panel;
    private javax.swing.JButton syncModpackButton;
    private javax.swing.JMenuItem syncModpackContextMenuItem;
    private javax.swing.JMenuItem syncModpackMenuItem;
    private javax.swing.JMenuItem syncNewModpackContextMenuItem;
    private javax.swing.JMenuItem syncNewModpackMenuItem;
    private javax.swing.JTabbedPane tabbedPane;
    private javax.swing.JMenuItem viewModInformationContextMenuItem;
    private javax.swing.JMenuItem viewModpackInformationContextMenuItem;
    // End of variables declaration//GEN-END:variables
}
